﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Security.Permissions
Imports System.Threading

Namespace System.Runtime.Serialization
    Friend Class FormatterServicesNoSerializableCheck
        ' Methods
        Private Shared Function CheckSerializable(ByVal type As Type) As Boolean
            Return True
        End Function

        Private Shared Function GetParentTypes(ByVal parentType As Type, <Out> ByRef parentTypes As Type(), <Out> ByRef parentTypeCount As Integer) As Boolean
            parentTypes = Nothing
            parentTypeCount = 0
            Dim flag As Boolean = True
            Dim type As Type = parentType
            Do While (Not type Is GetType(Object))
                If type.IsInterface Then
                    [Continue] Do
                End If
                Dim name As String = type.Name
                Dim i As Integer = 0
                Do While (flag AndAlso (i < parentTypeCount))
                    Dim str2 As String = parentTypes(i).Name
                    If (((str2.Length = name.Length) AndAlso (str2.Chars(0) = name.Chars(0))) AndAlso (name = str2)) Then
                        flag = False
                        Exit Do
                    End If
                    i += 1
                Loop
                If ((parentTypes Is Nothing) OrElse (parentTypeCount Is parentTypes.Length)) Then
                    Dim destinationArray As Type() = New Type(Math.Max((parentTypeCount * 2), 12)  - 1) {}
                    If (Not parentTypes Is Nothing) Then
                        Array.Copy(parentTypes, 0, destinationArray, 0, parentTypeCount)
                    End If
                    parentTypes = destinationArray
                End If
                parentTypes(parentTypeCount++) = type
                type = type.BaseType
            Loop
            Return flag
        End Function

        <SecurityPermission(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Public Shared Function GetSerializableMembers(ByVal type As Type, <Out> ByRef names As String()) As MemberInfo()
            Dim name As MemberInfoName
            names = Nothing
            If (type Is Nothing) Then
                Throw New ArgumentNullException("type")
            End If
            SyncLock FormatterServicesNoSerializableCheck.formatterServicesSyncObject
                If FormatterServicesNoSerializableCheck.m_MemberInfoTable.TryGetValue(type, name) Then
                    names = name.Names
                    Return name.MemberInfo
                End If
            End SyncLock
            name.MemberInfo = FormatterServicesNoSerializableCheck.InternalGetSerializableMembers(type, name.Names)
            SyncLock FormatterServicesNoSerializableCheck.formatterServicesSyncObject
                Dim name2 As MemberInfoName
                If FormatterServicesNoSerializableCheck.m_MemberInfoTable.TryGetValue(type, name2) Then
                    names = name2.Names
                    Return name2.MemberInfo
                End If
                FormatterServicesNoSerializableCheck.m_MemberInfoTable.Item(type) = name
            End SyncLock
            names = name.Names
            Return name.MemberInfo
        End Function

        Private Shared Function GetSerializableMembers2(ByVal type As Type) As MemberInfo()
            Dim fields As FieldInfo() = type.GetFields((BindingFlags.NonPublic Or (BindingFlags.Public Or BindingFlags.Instance)))
            Dim index As Integer = 0
            Dim i As Integer
            For i = 0 To fields.Length - 1
                If ((fields(i).Attributes And FieldAttributes.NotSerialized) <> FieldAttributes.NotSerialized) Then
                    index += 1
                End If
            Next i
            If (index = fields.Length) Then
                Return fields
            End If
            Dim infoArray2 As FieldInfo() = New FieldInfo(index  - 1) {}
            index = 0
            Dim j As Integer
            For j = 0 To fields.Length - 1
                If ((fields(j).Attributes And FieldAttributes.NotSerialized) <> FieldAttributes.NotSerialized) Then
                    infoArray2(index) = fields(j)
                    index += 1
                End If
            Next j
            Return infoArray2
        End Function

        Private Shared Function InternalGetSerializableMembers(ByVal type As Type, <Out> ByRef typeNames As String()) As MemberInfo()
            typeNames = Nothing
            Dim list As ArrayList = Nothing
            Dim list2 As ArrayList = Nothing
            If type.IsInterface Then
                Return New MemberInfo(0  - 1) {}
            End If
            Dim sourceArray As MemberInfo() = FormatterServicesNoSerializableCheck.GetSerializableMembers2(type)
            If (Not sourceArray Is Nothing) Then
                typeNames = New String(sourceArray.Length  - 1) {}
                Dim i As Integer
                For i = 0 To sourceArray.Length - 1
                    typeNames(i) = sourceArray(i).Name
                Next i
            End If
            Dim baseType As Type = type.BaseType
            If ((Not baseType Is Nothing) AndAlso (Not baseType Is GetType(Object))) Then
                Dim parentTypes As Type() = Nothing
                Dim parentTypeCount As Integer = 0
                Dim flag As Boolean = FormatterServicesNoSerializableCheck.GetParentTypes(baseType, parentTypes, parentTypeCount)
                If (parentTypeCount <= 0) Then
                    Return sourceArray
                End If
                list = New ArrayList
                list2 = New ArrayList
                Dim j As Integer
                For j = 0 To parentTypeCount - 1
                    baseType = parentTypes(j)
                    If Not FormatterServicesNoSerializableCheck.CheckSerializable(baseType) Then
                        Throw New SerializationException
                    End If
                    Dim fields As FieldInfo() = baseType.GetFields((BindingFlags.NonPublic Or BindingFlags.Instance))
                    Dim str As String = If(flag, baseType.Name, baseType.FullName)
                    Dim info As FieldInfo
                    For Each info In fields
                        If (info.IsPrivate AndAlso Not info.IsNotSerialized) Then
                            list.Add(info)
                            list2.Add((str & FormatterServicesNoSerializableCheck.FakeNameSeparatorString & info.Name))
                        End If
                    Next
                Next j
                If ((Not list Is Nothing) AndAlso (list.Count > 0)) Then
                    Dim destinationArray As MemberInfo() = New MemberInfo((list.Count + sourceArray.Length)  - 1) {}
                    Array.Copy(sourceArray, destinationArray, sourceArray.Length)
                    list.CopyTo(destinationArray, sourceArray.Length)
                    sourceArray = destinationArray
                    Dim strArray As String() = New String((list2.Count + typeNames.Length)  - 1) {}
                    Array.Copy(typeNames, strArray, typeNames.Length)
                    list2.CopyTo(strArray, typeNames.Length)
                    typeNames = strArray
                End If
            End If
            Return sourceArray
        End Function


        ' Properties
        Private Shared ReadOnly Property formatterServicesSyncObject As Object
            Get
                If (FormatterServicesNoSerializableCheck.s_FormatterServicesSyncObject Is Nothing) Then
                    Dim obj2 As New Object
                    Interlocked.CompareExchange((FormatterServicesNoSerializableCheck.s_FormatterServicesSyncObject), obj2, Nothing)
                End If
                Return FormatterServicesNoSerializableCheck.s_FormatterServicesSyncObject
            End Get
        End Property


        ' Fields
        Friend Shared ReadOnly FakeNameSeparatorString As String = "+"
        Private Shared m_MemberInfoTable As Dictionary([Of] Type, MemberInfoName) = New Dictionary([Of] Type, MemberInfoName)(&H20)
        Private Shared s_FormatterServicesSyncObject As Object = Nothing

        ' Nested Types
        <StructLayout(LayoutKind.Sequential)> _
        Private Structure MemberInfoName
            Public MemberInfo As MemberInfo()
            Public Names As String()
        End Structure
    End Class
End Namespace

